namespace AndyPike.Unfuddle.Contracts
{
    /// <summary>
    /// Provides an interface for Unfuddle services
    /// </summary>
    public interface IUnfuddleService
    {
        /// <summary>
        /// Allows the caller to change the default HttpWebRequestFactory if required
        /// </summary>
        IHttpWebRequestFactory HttpWebRequestFactory { get; set; }

        /// <summary>
        /// Creates an Unfuddle resource url for a particular action
        /// </summary>
        /// <param name="action">The action part of the url, for example: projects/{id}</param>
        /// <param name="args">Format args used to replace {n} in the action param</param>
        /// <returns>Returns the fully constructed resource url</returns>
        string BuildUrl(string action, params object[] args);

        /// <summary>
        /// Makes the http request for the given url and deserializes the response. Also checks the http 
        /// status code and throws exceptions as required. Defaults to GET http verb and doesn't include a request body.
        /// </summary>
        /// <typeparam name="T">The entity type that should be deserialized</typeparam>
        /// <param name="url">The Unfuddle url to request</param>
        /// <returns>Returns the deserialized object from the response</returns>
        T InvokeRequest<T>(string url) where T : class, IEntity;

        /// <summary>
        /// Makes the http request for the given url and deserializes the response. Also checks the http status code and throws exceptions as required
        /// </summary>
        /// <typeparam name="T">The entity type that should be deserialized</typeparam>
        /// <param name="url">The Unfuddle url to request</param>
        /// <param name="httpMethod">The http verb tp use when issuing the request</param>
        /// <param name="entityToSend">The entity to serialize and send as part of the request body</param>
        /// <returns>Returns the deserialized object from the response</returns>
        T InvokeRequest<T>(string url, HttpMethod httpMethod, T entityToSend) where T : class, IEntity;

        /// <summary>
        /// Executes an Unfuddle find command on this service
        /// </summary>
        /// <typeparam name="T">The type to return from the execution of this command</typeparam>
        /// <param name="command">The Unfuddle command to execute</param>
        /// <returns>Returns the result of the command (type T)</returns>
        T Execute<T>(IUnfuddleFindCommand<T> command);

        /// <summary>
        /// Executes an Unfuddle change command on this service
        /// </summary>
        /// <param name="command">The Unfuddle command to execute</param>
        void Execute(IUnfuddleChangeCommand command);
    }
}